# Copyright (c) 2022 Robert Bosch GmbH and Microsoft Corporation
#
# This program and the accompanying materials are made available under the
# terms of the Apache License, Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# SPDX-License-Identifier: Apache-2.0

"""A sample skeleton vehicle app."""


import json
import logging

from sdv.util.log import (  # type: ignore
    get_opentelemetry_log_factory,
    get_opentelemetry_log_format,
)
from sdv.vehicle_app import VehicleApp, subscribe_topic
from vehicle import Vehicle  # type: ignore

# Configure the VehicleApp logger with the necessary log config and level.
logging.setLogRecordFactory(get_opentelemetry_log_factory())
logging.basicConfig(format=get_opentelemetry_log_format())
logging.getLogger().setLevel("DEBUG")
logger = logging.getLogger(__name__)

GET_DOOR_REQUEST_TOPIC = "doorcontrol/setOpen/request"
GET_DOOR_RESPONSE_TOPIC = "doorcontrol/setOpen/response"


class DoorControlApp(VehicleApp):

    def __init__(self, vehicle_client: Vehicle):
        # SampleApp inherits from VehicleApp.
        super().__init__()
        self.Vehicle = vehicle_client

    async def on_start(self):
        """Run when the vehicle app starts"""
        # This method will be called by the SDK when the connection to the
        # Vehicle DataBroker is ready.
        # Here you can subscribe for the Vehicle Signals update
        # (e.g. Vehicle.Cabin.Door.Row1.Left.IsOpen).
        logger.info("begin on start function")

    @subscribe_topic(GET_DOOR_REQUEST_TOPIC)
    async def on_set_door_request_received(self, data_str: str) -> None:
        """The subscribe_topic annotation is used to subscribe for incoming
        PubSub events, e.g. MQTT event for GET_DOOR_REQUEST_TOPIC.
        """

        # Use the logger with the preferred log level (e.g. debug, info, error, etc)
        logger.debug(
            "PubSub event for the Topic: %s -> is received with the data: %s",
            GET_DOOR_REQUEST_TOPIC,
            data_str,
        )

        # Getting current door from VehicleDataBroker using the DataPoint getter.
        door_status = (await self.Vehicle.Cabin.Door.Row1.Left.IsOpen.get()).value
        logger.info("door_status: %s", door_status)
        # request door state
        data = json.loads(data_str)
        status = data["status"]
        if status:
            message = "open"
        else:
            message = "close"
        if status != door_status:
            await self.Vehicle.Cabin.Door.Row1.Left.IsOpen.set(status)
            await self.publish_event(
                GET_DOOR_RESPONSE_TOPIC,
                json.dumps(
                    {
                        "result": {
                            "status": 0,
                            "message": f"""door state changed to {message}""",
                        },
                    }
                ),
            )
        else:
            await self.publish_event(
                GET_DOOR_RESPONSE_TOPIC,
                json.dumps(
                    {
                        "result": {
                            "status": 0,
                            "message": f"""current door state already {message}""",
                        },
                    }
                ),
            )

